package com.caifeng.log;

import com.caifeng.domain.ServiceException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;

@Aspect
@Component
public class LogSender {

    @Resource
    RabbitTemplate rabbitTemplate;

    @Around("@annotation(com.caifeng.log.MiaoLog)")
    public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
        Log log = new Log();

        long startTime = System.currentTimeMillis();

        Method method = ((MethodSignature) pjp.getSignature()).getMethod();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        log.setUserId(authentication == null ? "null" : authentication.getName());
        log.setStartTime(new Date(startTime));
        log.setDescription(method.getAnnotation(MiaoLog.class).value());
        log.setUrl(String.valueOf(request.getRequestURL()));
        log.setMethod(request.getMethod());
        log.setParameter(Arrays.toString(pjp.getArgs()));
        log.setIp(request.getRemoteAddr());
        try {
            Object result = pjp.proceed();
            log.setResult(String.valueOf(result));
            log.setStatus("SUCCESS");
            return result;
        } catch (ServiceException e) {
            log.setException(e.getCode().getMsg() + ":" + e.getDescription().description());
            log.setStatus("WORN");
            throw e;
        } catch (Throwable e) {
            log.setException(e.getMessage());
            log.setStatus("ERROR");
            throw e;
        } finally {
            long endTime = System.currentTimeMillis();
            log.setSpendTime(endTime - startTime);
            rabbitTemplate.convertAndSend("common.direct", "log", log);
        }
    }
}
